package cn.fboost.mtos.service.impl;

import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.fboost.mtos.dto.Response;
import cn.fboost.mtos.dto.internal.Session;
import cn.fboost.mtos.dto.request.AdminLoginRequest;
import cn.fboost.mtos.dto.request.WechatLoginRequest;
import cn.fboost.mtos.dto.response.AdminInfoResponse;
import cn.fboost.mtos.dto.response.UserInfoResponse;
import cn.fboost.mtos.entity.Admin;
import cn.fboost.mtos.entity.User;
import cn.fboost.mtos.mapper.AdminMapper;
import cn.fboost.mtos.mapper.UserMapper;
import cn.fboost.mtos.service.AuthService;
import cn.fboost.mtos.util.ContextHolderUtil;
import cn.fboost.mtos.util.EncryptUtil;
import cn.fboost.mtos.util.SessionUtil;
import cn.fboost.mtos.util.WeChatUtil;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.UUID;

@Slf4j
@Service
public class AuthServiceImpl implements AuthService {
    private final AdminMapper adminMapper;
    private final UserMapper userMapper;
    private final WeChatUtil weChatUtil;
    private final SessionUtil sessionUtil;

    public AuthServiceImpl(AdminMapper adminMapper, UserMapper userMapper, WeChatUtil weChatUtil, SessionUtil sessionUtil) {
        this.adminMapper = adminMapper;
        this.userMapper = userMapper;
        this.weChatUtil = weChatUtil;
        this.sessionUtil = sessionUtil;
    }

    @Override
    public Response wechatLogin(WechatLoginRequest request) {
        try {
            // 利用code从微信服务器获取openid
            WxMaJscode2SessionResult sessionInfo = weChatUtil.getWxMaService().getUserService()
                    .getSessionInfo(request.getCode());

            User user = userMapper.findByWechatOpenID(sessionInfo.getOpenid());
            if (user == null) {
                user = new User();
                user.setNickname("微信用户" + sessionInfo.getOpenid().substring(0, 5));
                user.setWechatOpenId(sessionInfo.getOpenid());
                if (userMapper.create(user) == 0) {
                    return Response.builder().failure().msg("注册失败，请重试").build();
                }
            }

            // 生成token和session存入redis
            Session session = new Session();
            session.setRole(Session.Role.USER);
            session.setId(user.getId());
            session.setUser(user);

            String token = UUID.randomUUID().toString();
            sessionUtil.setSession(token, session);
            return Response.builder().success().msg("登录成功").data(token).build();
        } catch (WxErrorException e) {
            log.error("Wechat mini program login failed: {}", e.getError().getErrorMsg());
            return Response.builder().failure().msg("微信服务器返回错误").build();
        }
    }

    @Override
    public Response adminLogin(AdminLoginRequest request) {
        Admin admin = adminMapper.findByUsername(request.getUsername());
        if (admin == null || !Objects.equals(EncryptUtil.encryptPassword(request.getPassword()), admin.getPassword())) {
            return Response.builder().failure().msg("用户名或密码错误").build();
        }

        // 生成token和session存入redis
        Session session = new Session();
        session.setRole(Session.Role.ADMIN);
        session.setId(admin.getId());
        session.setAdmin(admin);

        String token = UUID.randomUUID().toString();
        sessionUtil.setSession(token, session);
        return Response.builder().success().msg("登录成功").data(token).build();
    }

    @Override
    public Response logout() {
        String token = ContextHolderUtil.getAccessToken();
        if (token != null) {
            sessionUtil.deleteSession(token);
        }

        return Response.builder().success().msg("退出成功").build();
    }

    @Override
    public Response getInfo() {
        Session session = ContextHolderUtil.getCurrentSession();
        Object info;
        if (session.getRole() == Session.Role.USER) {
            UserInfoResponse response = new UserInfoResponse();
            response.setId(session.getId());
            response.setNickname(session.getUser().getNickname());

            info = response;
        } else if (session.getRole() == Session.Role.ADMIN) {
            AdminInfoResponse response = new AdminInfoResponse();
            response.setId(session.getId());
            response.setUsername(session.getAdmin().getUsername());

            info = response;
        } else {
            info = null;
        }

        return Response.builder().msg("获取成功").data(info).build();
    }
}
